package com.mijie.homi.api;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mijie.core.Status;
import com.mijie.exception.RecordNotFoundException;
import com.mijie.homi.common.constant.HomiConstants;
import com.mijie.homi.common.constant.HomiStatusCode;
import com.mijie.homi.common.domain.mood.Mood;
import com.mijie.homi.common.domain.mood.MoodFigure;
import com.mijie.homi.common.domain.mood.MoodInfo;
import com.mijie.homi.common.domain.user.DeviceInfo;
import com.mijie.homi.common.domain.user.User;
import com.mijie.homi.common.domain.user.UserExtInfo;
import com.mijie.homi.common.util.HomiUtil;
import com.mijie.homi.domain.mood.MoodStat;
import com.mijie.homi.service.common.CommentService.COMMENT;
import com.mijie.homi.service.common.ReplyService.REPLY;
import com.mijie.homi.service.mood.MoodBroadcastService;
import com.mijie.homi.service.mood.MoodFigureService;
import com.mijie.homi.service.mood.MoodService;
import com.mijie.homi.service.user.DeviceInfoService;
import com.mijie.homi.service.user.FriendService;
import com.mijie.homi.service.user.MoodUserService;
import com.mijie.homi.service.user.PrivacyService;
import com.mijie.homi.service.user.UserExtInfoService;
import com.mijie.homi.service.user.UserService;
import com.mijie.homi.util.ServerHelper;
import com.mijie.util.DateUtil;
import com.mijie.util.Helper;
import com.mijie.util.IOUtil;

@Controller
@RequestMapping("/mood")
public class MoodApi extends CommomApi{
	
	@Autowired
	private MoodService moodService;
	@Autowired
	private MoodUserService moodUserService;
	@Autowired
	private MoodFigureService moodFigureService;
	@Autowired
	private UserService userService;
	@Autowired
	private UserExtInfoService userExtInfoService;
	@Autowired
	private PrivacyService privacyService;
	@Autowired
	private DeviceInfoService deviceInfoService;
	@Autowired
	private FriendService friendService;
	@Autowired
	private MoodBroadcastService moodBroadcastService;

	private Logger logger = Logger.getLogger(MoodApi.class);
	
	@RequestMapping(value="/content/clear",method=RequestMethod.GET)
	public @ResponseBody void clearContent(long id,HttpServletRequest request,HttpServletResponse response) throws IOException{
		Mood mood = moodService.getMoodById(id);
		Integer userId = ServerHelper.getUserId(request);
		Status status = new Status(request,response);
		if(mood==null){
			status.setCode(HomiStatusCode.RECORD_NOT_FOUND);
		}else{
			if(userId==mood.getUserId()){
				int succ = moodService.clearMoodContent(id);
				if(succ==0)
					status.setCode(HomiStatusCode.API_EXCEPTION);
			}else{
				status.setCode(HomiStatusCode.PERMISSION_ERROR);
			}
		}
		status.write();
	}
	
	
	@RequestMapping(value="/stat",method=RequestMethod.GET)
	public @ResponseBody void stat(HttpServletRequest request,HttpServletResponse response){
		Status status = new Status(request,response);
		Date now = new Date();
		int userId = ServerHelper.getUserId(request);
		MoodStat stat = moodService.getMoodStatByUserId(userId);
		UserExtInfo extInfo = this.userExtInfoService.getUserExtInfoByUserId(userId);
		HashMap<Integer,Integer> attachment = null;
		JSONObject result = new JSONObject();
		if(stat!=null || (stat==null && extInfo.getNumOfMood()>0 && DateUtil.isSameDay(extInfo.getCreateAt(), now))){
			List<Mood> moodList = moodService.listTodayMood(userId);
			Integer count = null;
			for(Mood mood : moodList){
				if(attachment==null) attachment = new HashMap<Integer,Integer>();
				count = attachment.get(mood.getMood());
				if(count==null) count = 1;
				else count++;
				attachment.put(mood.getMood(), count);
			}
		}
		
		if(stat==null) stat = new MoodStat();
		
		result.accumulate("nearly14Days", parseStat(stat.getNearly14Days(),attachment));
		result.accumulate("nearly30Days", parseStat(stat.getNearly30Days(),attachment));
		result.accumulate("nearly90Days", parseStat(stat.getNearly90Days(),attachment));
		result.accumulate("overall", parseStat(stat.getOverall(),attachment));
		result.accumulate("statAt", stat.getStatAt()!=null?stat.getStatAt().getTime():attachment==null?0:now.getTime());
		status.setResult(result);
		status.write();
	}
	
	private JSONObject parseStat(String statStr,HashMap<Integer,Integer> attachment){
		String[] statEntry = null;
		String[] pair = null;
		Integer mood = null;
		Integer count = null;
		JSONObject json = new JSONObject();;
		if(statStr!=null && !statStr.trim().isEmpty()){
			statEntry = statStr.split(",");
			if(statEntry!=null){
				for(String entry : statEntry){
					pair = entry.split(":");
					mood = Integer.parseInt(pair[0]);
					count = Integer.parseInt(pair[1]);
					if(attachment!=null && !attachment.isEmpty() && attachment.containsKey(mood)) count+=attachment.get(mood);
					json.put(mood, count);
				}
			}
		}else{
			if(attachment!=null && !attachment.isEmpty()){
				for(Integer m : attachment.keySet()){
					json.put(m, attachment.get(m));
				}
			}
		}
		return json;
	}
	
	@RequestMapping(value="/post",method=RequestMethod.POST)
	public @ResponseBody void postMood(HttpServletRequest request,HttpServletResponse response) throws IOException{
		String content = IOUtil.getContent4InputStream(request.getInputStream());
		JSONObject json = JSONObject.fromObject(content);
		Status status = new Status(request,response);
		Mood mood = (Mood) JSONObject.toBean(json, Mood.class);
		if(mood.getContent()==null){
			status.setCode(HomiStatusCode.PARAM_ABSENT);
			status.write();
			return;
		}
		
		if(mood.getContent().length()>HomiConstants.MAX_WORD_MOOD_SHARE){
			status.setCode(HomiStatusCode.CONTENT_LENGTH_LIMIT);
			status.write();
			return;
		}
		
		Integer userId = ServerHelper.getUserId(request);
		mood.setUserId(userId);
		mood.setCreateAt(new Date());
		int rows = 0;
		try{
			rows = moodService.postMood(mood);
		}catch(Exception e){
			logger.error("content:"+mood.getContent()+",keyword:"+mood.getKeyword());
			logger.error(e.getMessage(), e);
		}
		if(rows==0){
			status.setCode(HomiStatusCode.API_EXCEPTION);
		}else{
			JSONObject info = new JSONObject();
			info.accumulate("id", mood.getId());
			info.accumulate("timelineId", mood.getTimelineId());
			info.accumulate("publishingAddress", mood.getPublishingAddress());
			status.setResult(info.toString());
		}
			
		status.write();
	}
	
	@RequestMapping(value="/repost",method=RequestMethod.POST)
	public @ResponseBody void repostMood(HttpServletRequest request,HttpServletResponse response) throws IOException{
		String content = IOUtil.getContent4InputStream(request.getInputStream());
		
		JSONObject json = JSONObject.fromObject(content);
		Status status = new Status(request,response);
		Mood mood = (Mood) JSONObject.toBean(json, Mood.class);
		if(mood.getContent()==null){
			status.setCode(HomiStatusCode.PARAM_ABSENT);
			status.write();
			return;
		}
		
		if(mood.getContent().length()>HomiConstants.MAX_WORD_MOOD_SHARE){
			status.setCode(HomiStatusCode.CONTENT_LENGTH_LIMIT);
			status.write();
			return;
		}
		
		Integer userId = ServerHelper.getUserId(request);
		mood.setUserId(userId);
		int rows = 0;
		try{
			rows = moodService.repostMood(mood);
		}catch(Exception e){
			logger.error("content:"+mood.getContent()+",keyword:"+mood.getKeyword());
			logger.error(e.getMessage(), e);
		}
		if(rows==0)
			status.setCode(HomiStatusCode.API_EXCEPTION);
		status.write();
	}
	
	@RequestMapping(value="/view/apply",method=RequestMethod.GET)
	public @ResponseBody void applyView(int id,HttpServletRequest request,HttpServletResponse response) throws IOException{
		Status status = new Status(request,response);
		Mood mood = moodService.getMoodById(id);
		if(mood!=null){
			moodService.applyView(ServerHelper.getUserId(request), mood);
		}else{
			status.setCode(HomiStatusCode.RECORD_NOT_FOUND);
		}
		status.write();
	}
	
	@RequestMapping(value="/view/apply/accept",method=RequestMethod.GET)
	public @ResponseBody void acceptView(int id,int viewer,HttpServletRequest request,HttpServletResponse response) throws IOException{
		Status status = new Status(request,response);
		Mood mood = moodService.getMoodById(id);
		if(mood!=null){
			if(mood.getUserId()==ServerHelper.getUserId(request)){
				moodService.acceptViewApply(viewer, mood);
			}else{
				status.setCode(HomiStatusCode.PERMISSION_ERROR);
			}
		}else{
			status.setCode(HomiStatusCode.RECORD_NOT_FOUND);
		}
		status.write();
	}
	
	@RequestMapping(value="/view/apply/reject",method=RequestMethod.GET)
	public @ResponseBody void rejectView(int id,int viewer,HttpServletRequest request,HttpServletResponse response) throws IOException{
		Status status = new Status(request,response);
		Mood mood = moodService.getMoodById(id);
		if(mood!=null){
			if(mood.getUserId()==ServerHelper.getUserId(request)){
				moodService.rejectViewApply(viewer, mood);
			}else{
				status.setCode(HomiStatusCode.PERMISSION_ERROR);
			}
		}else{
			status.setCode(HomiStatusCode.RECORD_NOT_FOUND);
		}
		status.write();
	}
	
	@RequestMapping(value="/setVisibility",method=RequestMethod.POST)
	public @ResponseBody void setVisibility(HttpServletRequest request,HttpServletResponse response) throws IOException{
		String content = IOUtil.getContent4InputStream(request.getInputStream());
		JSONObject json = JSONObject.fromObject(content);
		Status status = new Status(request,response);
		if(json.containsKey("id") && json.containsKey("visibility") && json.containsKey("allowedToApply")){
			int userId = ServerHelper.getUserId(request);
			int succ = moodService.setVisibility(json.getLong("id"), userId, json.getInt("visibility"), json.getInt("allowedToApply"));
			if(succ==0)
				status.setCode(HomiStatusCode.API_EXCEPTION);
		}else{
			status.setCode(HomiStatusCode.PARAM_ABSENT);
		}
		status.write();
	}
	
	@RequestMapping(value="/broadcast",method=RequestMethod.POST)
	public @ResponseBody void broadcast(HttpServletRequest request,HttpServletResponse response) throws IOException{
		String content = IOUtil.getContent4InputStream(request.getInputStream());
		JSONObject json = JSONObject.fromObject(content);
		Status status = new Status(request,response);
		if(json.containsKey("id")){
			int userId = ServerHelper.getUserId(request);
			Mood mood = moodService.getMoodById(json.getLong("id"));
			if(mood!=null){
				if(mood.getUserId()==userId){
					int succ = moodService.setBroadcasted(mood.getId());
					if(succ>0){
						mood.setBroadcasted(1);
						moodBroadcastService.addToMoodPushQueue(mood);
					}
				}else{
					status.setCode(HomiStatusCode.PERMISSION_ERROR);
				}
			}else{
				status.setCode(HomiStatusCode.RECORD_NOT_FOUND);
			}
		}else{
			status.setCode(HomiStatusCode.PARAM_ABSENT);
		}
		status.write();
	}
	
	@RequestMapping(value="/list",method=RequestMethod.GET)
	public @ResponseBody void list(int userId,int offset,int limit,
			HttpServletRequest request,HttpServletResponse response){
		int requester = ServerHelper.getUserId(request);
		Status status = new Status(request,response);
		List<Mood> list = moodService.listMood(userId, offset, limit);
		JSONArray result = new JSONArray();
		if(!list.isEmpty()){
			List<Long> moodIds = new ArrayList<Long>(list.size());
			for(int i=0;i<list.size();i++) moodIds.add(list.get(i).getId()); 
			Set<Long> viewPrivilege = moodService.listMoodIdByViewPrivlege(requester,moodIds);
			JSONObject json = null;
			Mood mood = null;
			Iterator<Mood> iter = list.iterator();
			User user = null;
			boolean isFriend = true;
			if(userId!=requester)
				isFriend = friendService.isFriend(userId, requester);
			while(iter.hasNext()){
				mood = iter.next();
				iter.remove();
				json = JSONObject.fromObject(mood);
				user = userService.getUserById(mood.getUserId());
				json.put("isFriend", isFriend);
				json.put("viewPrivilege", viewPrivilege.contains(mood.getId()));
				json.put("authorNickName", user.getNickName());
				json.put("authorAvatar", HomiUtil.getRealUrl(user.getAvatar()));
				json.put("createAt", mood.getCreateAt().getTime());
				result.add(json.toString());
			}
			iter = null;
			list = null;
		}
		status.setResult(result);
		status.write();
	}
	
	@RequestMapping(value="/response",method=RequestMethod.POST)
	public @ResponseBody void response(HttpServletRequest request,HttpServletResponse response) throws IOException{
		Status status = new Status(request,response);
		String content = IOUtil.getContent4InputStream(request.getInputStream());
		JSONObject json = JSONObject.fromObject(content);
		try {
			moodService.responseMood(ServerHelper.getUserId(request),json.getLong("id"));
		} catch (RecordNotFoundException e) {
			logger.error(e.getMessage(), e);
			status.setCode(HomiStatusCode.RECORD_NOT_FOUND);
		}
		
		status.write();
	}
	
	@RequestMapping(value="/response/cancel",method=RequestMethod.POST)
	public @ResponseBody void cancelResponseForMood(HttpServletRequest request,HttpServletResponse response) throws IOException{
		Status status = new Status(request,response);
		String content = IOUtil.getContent4InputStream(request.getInputStream());
		JSONObject json = JSONObject.fromObject(content);
		int rows = moodService.cancelResponseForMood(ServerHelper.getUserId(request),json.getLong("id"));
		if(rows==0) status.setCode(HomiStatusCode.API_EXCEPTION);
		status.write();
	}
	
	@RequestMapping(value="/response/users",method=RequestMethod.GET)
	public @ResponseBody void responserUsers(long id,int limit,HttpServletRequest request,HttpServletResponse response) throws IOException{
		Mood mood = moodService.getMoodById(id);
		Status status = new Status(request,response);
		if(mood==null){
			status.setCode(HomiStatusCode.RECORD_NOT_FOUND);
			status.write();
			return;
		}
		
		List<User> list = moodService.listMoodResponder(id, limit);
		JSONObject result = new JSONObject();
		JSONObject json = null;
		JSONArray users = new JSONArray();
		for(User user : list){
			json = new JSONObject();
			json.accumulate("id", user.getId());
			json.accumulate("gender", user.getGender());
			json.accumulate("avatar", HomiUtil.getRealUrl(user.getAvatar()));
			users.add(json);
		}
		result.accumulate("count", mood.getNumOfResponse());
		result.accumulate("users", users);
		status.setResult(result);
		status.write();
	}
	
	@RequestMapping(value="/get",method=RequestMethod.GET)
	public @ResponseBody void getMoodById(long id,HttpServletRequest request,HttpServletResponse response){
		Status status = new Status(request,response);
		Mood mood = moodService.getMoodById(id);
		if(mood!=null){
			User user = userService.getUserById(mood.getUserId());
			JSONObject result = JSONObject.fromObject(mood);
			result.put("authorNickName", user.getNickName());
			result.put("authorAvatar", HomiUtil.getRealUrl(user.getAvatar()));
			result.put("createAt", mood.getCreateAt().getTime());
			status.setResult(result.toString());
		}else{
			status.setCode(HomiStatusCode.RECORD_NOT_FOUND);
		}
		status.write();
	}
	
	@RequestMapping(value="/info/list",method=RequestMethod.GET)
	public @ResponseBody void listInfo(HttpServletRequest request,HttpServletResponse response){
		Status status = new Status(request,response);
		List<MoodInfo> list = moodService.listMoodInfo();
		JSONArray result = JSONArray.fromObject(list);
		status.setResult(result);
		status.write();
		list.clear();
		list = null;
	}
	
	@RequestMapping(value="/match/info",method=RequestMethod.GET)
	public @ResponseBody void matchInfo(HttpServletRequest request,HttpServletResponse response){
		Integer userId = ServerHelper.getUserId(request);
		Status status = new Status(request,response);
		JSONObject result = new JSONObject();
		Mood recentlyMood = moodService.getRecentlyMood(userId);
		if(recentlyMood==null){
			result.accumulate("numOfSameMoodUser", 0);
			result.accumulate("numOfMatchMoodUser", 0);
			result.accumulate("numOfSameExperienceUser", 0);
		}else{
			UserExtInfo extInfo = userExtInfoService.getUserExtInfoByUserId(userId);
			int[] mood = moodService.getMateOfMood(extInfo.getMood());
			int numOfSameMoodUser = moodUserService.getMoodUserAmount(extInfo.getMood());
			numOfSameMoodUser+=73;
			int numOfMatchMoodUser = 0;
			for(int m : mood){
				numOfMatchMoodUser += moodUserService.getMoodUserAmount(m);
			}
			numOfMatchMoodUser+=84;
			
			int numOfSameExperienceUser = 0;
			
			result.accumulate("numOfSameMoodUser", numOfSameMoodUser);
			result.accumulate("numOfMatchMoodUser", numOfMatchMoodUser);
			if(recentlyMood.getContent().trim().length()<=10)
				result.accumulate("numOfSameExperienceUser", 0);
			else
				result.accumulate("numOfSameExperienceUser", numOfMatchMoodUser + 32);
		}
		
		status.setResult(result);
		status.write();
	}
	
	@RequestMapping(value="/figure/list",method=RequestMethod.GET)
	public @ResponseBody void listFigure(HttpServletRequest request,HttpServletResponse response){
		Status status = new Status(request,response);
		List<MoodFigure> list = moodFigureService.listMoodFigure(8);
		JSONArray result = new JSONArray();
		JSONObject json = null;
		UserExtInfo extInfo = userExtInfoService.getUserExtInfoByUserId(ServerHelper.getUserId(request));
		DeviceInfo deviceInfo = deviceInfoService.getDeviceInfo(extInfo.getDeviceId());
		String figureSize = null;
		if(deviceInfo!=null && deviceInfo.getOs().equalsIgnoreCase("android") && deviceInfo.getScreenSize().contains("*")){
			String screenHeight = deviceInfo.getScreenSize().substring(deviceInfo.getScreenSize().indexOf("*")+1).trim();
			if(Helper.isInt(screenHeight)){
				int height = Integer.parseInt(screenHeight);
				if(height>=1280){
					figureSize = "1280";
				}else if(height>854 && height<1280){
					figureSize = "1280";
				}else if(height>480 && height<=854){
					figureSize = "854";
				}else if(height<=480){
					figureSize = "480";
				}
			}
		}
		if(figureSize==null) figureSize = "ios";
		String figurePrefixName = null;
		for(MoodFigure figure : list){
			int index = figure.getFigure().indexOf("_");
			if(index!=-1)
				figurePrefixName = figure.getFigure().substring(0,index+1);
			else figurePrefixName = null;
			json = new JSONObject();
			json.accumulate("id", figure.getId());
			json.accumulate("whisper", figure.getWhisper());
			json.accumulate("whisperAuthor", figure.getWhisperAuthor());
			json.accumulate("figure", figurePrefixName==null?"":HomiUtil.getRealUrl(figurePrefixName+figureSize+".jpg".intern()));
			json.accumulate("figureAuthor", figure.getFigureAuthor());
			result.add(json);
		}
		status.setResult(result);
		status.write();
		list.clear();
		list = null;
	}
	
	@RequestMapping(value="/comment/post",method=RequestMethod.POST)
	public @ResponseBody void postComment(HttpServletRequest request,HttpServletResponse response) 
			throws IOException{
		super.postComment(COMMENT.MOOD, request, response);
	}
	
	@RequestMapping(value="/comment/delete",method=RequestMethod.GET)
	public @ResponseBody void deleteComment(long id,long parentId,HttpServletRequest request,HttpServletResponse response) 
			throws IOException{
		super.deleteComment(COMMENT.MOOD, id,parentId, request, response);
	}
	
	@RequestMapping(value="/comment/admin/delete",method=RequestMethod.GET)
	public @ResponseBody void deleteCommentByAdmin(long id,long parentId,HttpServletRequest request,HttpServletResponse response) 
			throws IOException{
		super.deleteCommentByAdmin(COMMENT.MOOD, id,parentId, request, response);
	}
	
	@RequestMapping(value="/comment/list",method=RequestMethod.GET)
	public @ResponseBody void listComment(long idx,long targetId,int limit,HttpServletRequest request,HttpServletResponse response){
		super.listComment(COMMENT.MOOD, idx,targetId, limit, request, response);
	}
	
	@RequestMapping(value="/comment/reply/post",method=RequestMethod.POST)
	public @ResponseBody void postReply(HttpServletRequest request,HttpServletResponse response) 
			throws IOException{
		super.postReply(REPLY.MOOD_COMMENT, request, response);
	}
	
	@RequestMapping(value="/comment/reply/delete",method=RequestMethod.GET)
	public @ResponseBody void deleteReply(long id,long parentId,HttpServletRequest request,HttpServletResponse response) 
			throws IOException{
		super.deleteReply(REPLY.MOOD_COMMENT,id,parentId, request, response);
	}
	
	@RequestMapping(value="/comment/reply/admin/delete",method=RequestMethod.GET)
	public @ResponseBody void deleteReplyByAdmin(long id,long parentId,HttpServletRequest request,HttpServletResponse response) 
			throws IOException{
		super.deleteReplyByAdmin(REPLY.MOOD_COMMENT,id,parentId, request, response);
	}
	
	@RequestMapping(value="/comment/reply/list",method=RequestMethod.GET)
	public @ResponseBody void listReply(long idx,long targetId,int limit,HttpServletRequest request,HttpServletResponse response){
		super.listReply(REPLY.MOOD_COMMENT,idx, targetId, limit, request, response);
	}
	
	@RequestMapping(value="/review/post",method=RequestMethod.POST)
	public @ResponseBody void review(HttpServletRequest request,
			HttpServletResponse response) {
		super.review(this.moodService, request, response);
	}

	@RequestMapping(value="/review/delete",method=RequestMethod.POST)
	public @ResponseBody void deleteReview(HttpServletRequest request,HttpServletResponse response) {
		super.deleteReview(this.moodService, request, response);
	}

	@RequestMapping(value="/review/list",method=RequestMethod.GET)
	public @ResponseBody void listReview(long eventId, int offset,
			int limit, HttpServletRequest request, HttpServletResponse response) {
		super.listReview(this.moodService, eventId, offset, limit, request, response);
	}
}
